package com.wxl.common.serialport

import android.text.TextUtils

class Serials {

    companion object {

        private val mSerial = HashMap<String, Serial>()

        private val mSerialSingle = HashMap<String, Serial>()

        private val mSerialStartHex = HashMap<String, Serial>()

        private val mSerialSingleStartHex = HashMap<String, Serial>()

        private val mNoKeySerial = HashMap<String, Serial>()

        private val mHexSerial = HashMap<String, HashMap<HexStr, Serial>>()

        /**
         * 注册一个不需要匹配key值的回调策略
         */
        fun registerNoKeySerial(tag: String, value: Serial) {
            mNoKeySerial.put(tag, value)
        }

        /**
         * 取消一个不需要匹配key值的回调策略
         */
        fun unRegisterNoKeySerial(tag: String) {
            mNoKeySerial.remove(tag)
        }


        /**
         * 注册一个区间匹配策略
         */
        fun registerHexSingleKeySerial(key: String, start: Int, end: Int, value: Serial) {
            val hs = HexStr(key, start, end)
            if (!mHexSerial.containsKey(hs.toString())) {
                mHexSerial.put(hs.toString(), HashMap())
            }
            val map = mHexSerial[hs.toString()]
            map?.put(hs, value)
        }

        /**
         * 取消注册一个区间匹配策略
         */
        fun unRegisterHexSingleKeySerial(key: String, start: Int, end: Int) {
            val hs = HexStr(key, start, end)
            if (mHexSerial.containsKey(hs.toString())) {
                mHexSerial.remove(hs.toString())?.clear()
            }
        }


        /**
         * 注册一个区间匹配策略
         */
        fun registerHexSingleKeySerial(startHex:String,key: String, start: Int, end: Int, value: Serial) {
            val hs = HexStr(key, start, end,startHex)
            if (!mHexSerial.containsKey(hs.toString())) {
                mHexSerial.put(hs.toString(), HashMap())
            }
            val map = mHexSerial[hs.toString()]
            map?.put(hs, value)
        }

        /**
         * 取消注册一个区间匹配策略
         */
        fun unRegisterHexSingleKeySerial(startHex:String,key: String, start: Int, end: Int) {
            val hs = HexStr(key, start, end,startHex)
            if (mHexSerial.containsKey(hs.toString())) {
                mHexSerial.remove(hs.toString())?.clear()
            }
        }

        /**
         * 注册一个回调策略
         */
        fun registerSerial(key: String, value: Serial) {
            mSerial.put(key, value)
        }

        /**
         * 取消一个回调策略
         */
        fun unRegisterSerial(key: String) {
            mSerial.remove(key)
        }


        /**
         * 注册一个前部字符串匹配的单次回调策略
         */
        fun registerSingleStartHexSerial(key: String, value: Serial) {
            mSerialSingleStartHex.put(key, value)
        }

        /**
         * 取消一个前部字符串匹配的单次回调策略
         */
        fun unRegisterSingleStartHexSerial(key: String) {
            mSerialSingleStartHex.remove(key)
        }

        /**
         * 注册一个前部字符串匹配的回调策略
         */
        fun registerStartHexSerial(key: String, value: Serial) {
            mSerialStartHex.put(key, value)
        }

        /**
         * 取消一个前部字符串匹配的回调策略
         */
        fun unRegisterStartHexSerial(key: String) {
            mSerialStartHex.remove(key)
        }


        /**
         * 注册一个单次回调策略
         */
        fun registerSingleSerial(key: String, value: Serial) {
            mSerialSingle.put(key, value)
        }

        /**
         * 取消一个单次回调策略
         */
        fun unRegisterSingleSerial(key: String) {
            mSerialSingle.remove(key)
        }

        /**
         * 执行一个单次策略
         */
        internal fun loadSerial(key: String) {
            loadNoKeySerial(key)
            matchHexSerial(key)
            if (!TextUtils.equals(SerialCode.CODE_NO_MSG, key)) {
                val serial = mSerial[key]
                when {
                    serial != null -> {
                        serial.loadData(key)
                    }
                    mSerialSingle.containsKey(key) -> {
                        val serialSingle = mSerialSingle.remove(key)
                        serialSingle?.loadData(key)
                    }
                    else -> {
                        findStartHexSerial(key)?.loadData(key)
                        findStartSingleHexSerial(key)?.loadData(key)
                    }
                }
            }
        }


        /**
         * 去匹配区间策略
         */
        private fun matchHexSerial(key: String) {
            mHexSerial.forEach { hs ->
                hs.value.forEach {
                    if (key.length >= it.key.endIndex) {
                        if((!TextUtils.isEmpty(it.key.startHex)&&key.startsWith(it.key.startHex!!)) || TextUtils.isEmpty(it.key.startHex)) {
                            val s = key.substring(it.key.startIndex, it.key.endIndex)
                            if (TextUtils.equals(s, it.key.hex)) {
                                mHexSerial.remove(it.key.toString())?.clear()
                                it.value.loadData(key)
                                return
                            }
                        }
                    }
                }
            }
        }

        /**
         * 不做匹配拦截
         */
        private fun loadNoKeySerial(key: String) {
            mNoKeySerial.forEach {
                it.value.loadData(key)
            }
        }

        /**
         * 找单次前部匹配策略
         */
        private fun findStartSingleHexSerial(key: String): Serial? {
            mSerialSingleStartHex.forEach() {
                if (key.startsWith(it.key)) {
                    return mSerialSingleStartHex.remove(it.key)
                }
            }
            return null
        }

        /**
         * 找前部字符串匹配的key
         */
        private fun findStartHexSerial(key: String): Serial? {
            mSerialStartHex.forEach() {
                if (key.startsWith(it.key)) {
                    return it.value
                }
            }
            return null
        }


        open class HexStr {
            var hex: String
            var startIndex: Int
            var endIndex: Int
            var startHex:String?=null

            constructor(hex: String, startIndex: Int, endIndex: Int) {
                this.hex = hex
                this.startIndex = startIndex
                this.endIndex = endIndex
            }

            constructor(hex: String, startIndex: Int, endIndex: Int, startHex: String?) {
                this.hex = hex
                this.startIndex = startIndex
                this.endIndex = endIndex
                this.startHex = startHex
            }

            override fun toString(): String {
                return "HexStr(hex='$hex', startIndex=$startIndex, endIndex=$endIndex, startHex=$startHex)"
            }


        }

    }


}